// HSS.ServiceManager.cs
// ----------------------------------------------------------------------------
// Licensed under the MIT license
// http://www.opensource.org/licenses/mit-license.html
// ----------------------------------------------------------------------------
// HighSpeed-Solutions, LLC
// Copyright (c) 2001-2010
// ----------------------------------------------------------------------------
// File:       ServiceManager.cs
// Author:     HSS\gbanta
// Created:    08/12/2010
// Modified:   12/04/2010
// ----------------------------------------------------------------------------
namespace HSS
{
	#region Using Directives
	using System;
	using System.Security.Permissions;
	using System.ServiceProcess;

	#endregion

	#region ServiceManager
	/// <summary>
	/// ServiceManager provides a wrapper around basic Win32 Service, such as starting, stopping, retrieving the Service
	/// Description, Location or StartType.
	/// </summary>
	[ServiceControllerPermission(SecurityAction.Demand, Unrestricted = true)]
	[RegistryPermission(SecurityAction.Demand, Unrestricted = true)]
	public sealed class ServiceManager
	{
		#region Fields
		static string servicesKey = @"SYSTEM\CurrentControlSet\Services\";
		#endregion

		#region Constructors
		private ServiceManager() { }
		#endregion

		#region Properties
		/// <summary>
		/// Gets the Name of the Service.
		/// </summary>
		public string ServiceName
		{
			get { return _serviceName; }
		} string _serviceName;
		/// <summary>
		/// Is the Service Installed?
		/// </summary>
		public bool ServiceExist
		{
			get
			{
				Microsoft.Win32.RegistryKey key = null;
				try
				{
					key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(servicesKey + this.ServiceName);
					if (null == key)
						return false;

					string imagePath = key.GetValue("ImagePath", "Missing") as string;
					if ("Missing" == imagePath)
						return false;

					imagePath = imagePath.Replace(@"""", string.Empty);
					if (System.IO.File.Exists(imagePath))
						return true;
					else
						return false;
				}
				finally
				{
					if (null != key)
						key.Close();
				}
			}
		}
		/// <summary>
		/// Gets the Service ImagePath.
		/// </summary>
		public string ServiceLocation
		{
			get
			{
				Microsoft.Win32.RegistryKey key = null;
				try
				{
					key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(servicesKey + this.ServiceName);
					if (null == key)
						return string.Empty;

					string imagePath = key.GetValue("ImagePath", "Missing") as string;
					if ("Missing" == imagePath)
						return string.Empty;

					imagePath = imagePath.Replace(@"""", string.Empty);
					if (System.IO.File.Exists(imagePath))
						return imagePath;
					else
						return string.Empty;
				}
				finally
				{
					if (null != key)
						key.Close();
				}
			}
		}
		/// <summary>
		/// Gets the Service Description.
		/// </summary>
		public string ServiceDescription
		{
			get
			{
				Microsoft.Win32.RegistryKey key = null;
				try
				{
					key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(servicesKey + this.ServiceName);
					if (null == key)
						return string.Empty;

					string imagePath = key.GetValue("Description", "Missing") as string;
					if ("Missing" == imagePath)
						return string.Empty;
					return imagePath;
				}
				finally
				{
					if (null != key)
						key.Close();
				}
			}
		}
		/// <summary>
		/// Gets or sets the Service Start Type.
		/// </summary>
		/// <remarks>
		/// Automatic = 2
		/// Manual = 3
		/// Disabled = 4
		/// </remarks>
		public ServiceStartMode ServiceStartType
		{
			get
			{
				int start = 4;
				Microsoft.Win32.RegistryKey key = null;
				try
				{
					key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(servicesKey + this.ServiceName);
					if (null != key)
						start = (int)key.GetValue("Start", 4);
				}
				finally
				{
					if (null != key)
						key.Close();
				}
				return (ServiceStartMode)start;
			}
			set
			{
				Microsoft.Win32.RegistryKey key = null;
				try
				{
					key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(servicesKey + this.ServiceName, true);
					if (null != key)
						key.SetValue("Start", (int)value);
				}
				finally
				{
					if (null != key)
						key.Close();
				}
			}
		}
		/// <summary>
		/// Is the Service Running.
		/// </summary>
		public bool IsServiceRunning
		{
			get
			{
				if (this.ServiceExist)
					using (ServiceController sc = new ServiceController(this.ServiceName))
						return (sc.Status == ServiceControllerStatus.Running);

				return false;
			}
		}
		#endregion

		#region Methods
		/// <summary>
		/// Gets a ServiceManager Instance for the specified ServiceName
		/// </summary>
		/// <param name="serviceName">The name of the Service to retrieve</param>
		/// <returns>An instance of ServiceManager</returns>
		public static ServiceManager GetService(string serviceName)
		{
			ServiceManager su = new ServiceManager();
			su._serviceName = serviceName;
			return su;
		}
		/// <summary>
		/// Stops the Service.
		/// </summary>
		/// <param name="waitTime">The amount of time to wait for the service to stop</param>
		public void StopService(TimeSpan waitTime)
		{
			if (this.ServiceExist)
			{
				using (ServiceController sc = new ServiceController(this.ServiceName))
				{
					if (sc.Status != ServiceControllerStatus.Stopped |
						sc.Status != ServiceControllerStatus.StopPending)
					{
						sc.Stop();
						sc.WaitForStatus(ServiceControllerStatus.Stopped, waitTime);
					}
				}
			}
		}
		/// <summary>
		/// Starts the Service.
		/// </summary>
		/// <param name="waitTime">The amount of time to wait for the service to start</param>
		public void StartService(TimeSpan waitTime)
		{
			if (this.ServiceExist)
			{
				using (ServiceController sc = new ServiceController(this.ServiceName))
				{
					if (sc.Status == ServiceControllerStatus.Stopped)
					{
						sc.Start();
						sc.WaitForStatus(ServiceControllerStatus.Running, waitTime);
					}
				}
			}
		}
		#endregion
	}
	#endregion
}